﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Data;

namespace BDTabela
{
    public class Tabela
    {
        #region Atributos

        /// <summary>
        ///     Privados
        /// </summary>
        private MySqlConnection _conn;
        private string _strConn = "Persist Security Info=False;server=mysql02.jovensipr.com.br;database=jovensipr1;uid=jovensipr1;server=mysql02.jovensipr.com.br;database=jovensipr1;uid=jovensipr1;pwd=errw@ipr";
        private string _nameTable;
        private MySqlParameterCollection listaParametro { get; set; }
        private DataSet _data { get; set; }

        /// <summary>
        ///     Publicos
        /// </summary>
        
        #endregion

        #region SQls

        private string sql_padrao = @"SELECT * FROM {0}";

        #endregion

        #region Construtores

        public Tabela(string nameTable)
        {
            try
            {
                this._nameTable = nameTable;

                _data = new DataSet();

                _data.DataSetName = this._nameTable;

                listaParametro = new MySqlCommand().Parameters;
                listaParametro.Add(getParametro("handle", -1, MySqlDbType.Int32));

                seleciona();
            }
            catch (Exception ex)
            {
                throw new Exception("Falha na construção da tabela: " + ex.Message);
            }
        }

        #endregion

        #region Padrões tabela

        private void create()
        {
            _conn = new MySqlConnection(_strConn);

            try
            {
                _conn.Open();
            }
            catch
            {
                throw new Exception("Não foi possível estabelecer conexão.");
            }
        }

        private void destroy()
        {
            _conn.Close();
        }

        public MySqlParameter getParametro(string name, object value, MySqlDbType type)
        {
            MySqlParameter parametro = new MySqlParameter();
            parametro.ParameterName = name;
            parametro.Value = value;
            parametro.MySqlDbType = type;

            return parametro;
        }

        #endregion

        #region Consultas

        public bool seleciona()
        {
            string sql = String.Format(sql_padrao, _nameTable);

            bool where = false;

            if (!Equals(listaParametro, null) && listaParametro.Count > 0)
            {
                foreach (MySqlParameter parametro in listaParametro)
                {
                    if (!where)
                        sql += String.Format(" WHERE {0} = @{0}", parametro.ParameterName);
                    else
                    {
                        sql += String.Format(" AND {0} = @{0}", parametro.ParameterName);
                        where = true;
                    }
                }
            }
            else
                throw new Exception("Não existem parâmetros informados para execução SQL");

            sql += " ORDER BY HANDLE";

            return seleciona(sql);
        }

        public bool seleciona(string sql)
        {
            try
            {
                create();

                if (_conn.State == ConnectionState.Open)
                {
                    try
                    {
                        MySqlDataAdapter dataAdapter = new MySqlDataAdapter(sql, _conn);

                        if (!Equals(listaParametro, null) && listaParametro.Count > 0)
                        {
                            foreach (MySqlParameter parametro in listaParametro)
                                dataAdapter.SelectCommand.Parameters.Add(parametro);
                        }
                        else
                            throw new Exception("Não existem parâmetros informados para execução SQL");

                        dataAdapter.Fill(_data, _nameTable);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Erro ao realizar consulta: " + ex.Message);
                    }
                    finally
                    {
                        destroy();
                    }
                }
                else
                {
                    throw new Exception("Conexão não está aberta.");
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Falha conexão: " + ex.Message);
            }

            return true;
        }

        #endregion

        #region Persistência

        public bool Save(int handle)
        {
            string sql = String.Empty;
            if (!Equals(listaParametro, null) && listaParametro.Count > 0)
            {
                try
                {
                    if (handle > 0)
                        sql = "UPDATE st_pessoas SET ";
                    else
                        sql = "INSERT INTO st_pessoas ( {0} ) VALUES ( {1} )";

                    if (handle > 0)
                    {
                        long colunas = new Int64();
                        for (int i = 1; i < _data.Tables[0].Columns.Count; ++i)
                        {
                            foreach (MySqlParameter parametro in listaParametro)
                            {
                                bool primeiroElemento = true;
                                if (_data.Tables[0].Columns[i].ColumnName.Equals(parametro.ParameterName))
                                {
                                    if (primeiroElemento)
                                    {
                                        sql += String.Format(" {0} = @{0} ", parametro.ParameterName);
                                        primeiroElemento = false;
                                    }
                                    else
                                        sql += String.Format(", {0} = @{0} ", parametro.ParameterName);

                                    parametro.ParameterName = "@" + parametro.ParameterName;

                                    colunas++;
                                }
                            }
                        }

                        if (listaParametro.Count > colunas)
                            throw new Exception("Alguns atributos não foram encontradas");

                        sql += " WHERE handle = @handle";

                        listaParametro.Add(getParametro("@handle", handle, MySqlDbType.Int32));
                    }
                    else
                    {
                        string strColumns = String.Empty;
                        string strValues = String.Empty;

                        for (int i = 1; i < _data.Tables[0].Columns.Count; ++i)
                        {
                            if (listaParametro.Contains(_data.Tables[0].Columns[i].ColumnName))
                            {
                                int position = listaParametro.IndexOf(_data.Tables[0].Columns[i].ColumnName);
                                if (i > 0)
                                {
                                    strColumns += String.Format(", {0} ", listaParametro[position].ParameterName);
                                    listaParametro[position].ParameterName = "@" + listaParametro[position].ParameterName;
                                    strValues += String.Format(", {0} ", listaParametro[position].ParameterName);
                                }
                                else
                                {
                                    strColumns += String.Format(" {0} ", listaParametro[position].ParameterName);
                                    listaParametro[position].ParameterName = "@" + listaParametro[position].ParameterName;
                                    strValues += String.Format(" {0} ", listaParametro[position].ParameterName);
                                }
                            }
                            else
                            {
                                if (i > 0)
                                {
                                    strColumns += String.Format(", {0} ", _data.Tables[0].Columns[i].ColumnName);
                                    strValues += String.Format(", {0} ", "NULL");
                                }
                                else
                                {
                                    strColumns += String.Format(" {0} ", _data.Tables[0].Columns[i].ColumnName);
                                    strValues += String.Format(" {0} ", "NULL");
                                }
                            }
                        }

                        sql = String.Format(sql, strColumns, strValues);
                    }

                    try
                    {
                        create();

                        MySqlCommand command = new MySqlCommand();
                        command.CommandText = sql;
                        foreach (MySqlParameter param in listaParametro)
                            command.Parameters.Add(param);
                        command.Connection = this._conn;

                        if (command.ExecuteNonQuery() > 0)
                            return true;
                        else
                            return false;
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Falha na persistência: " + ex.Message);
                    }
                    finally
                    {
                        destroy();
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("Error durante processo: " + ex.Message);
                }
            }
            else
                throw new Exception("Não existem parâmetros informados para execução SQL");
        }
        
        #endregion
    }
}
